import java.awt.*;
import java.awt.geom.AffineTransform;

public class DMastaGX extends Player implements Runnable {
	
	// Main Character
	public static DMastaGX MasterGX;
	
	// Animation Variables Looking Right
		public static Animation StandingRIGHT = AnimationLoader.megaStandRight();
		public static Animation RunningRIGHT = AnimationLoader.megaRunRight();
		public static Animation JumpingRIGHT = AnimationLoader.megaJumpRight();
		public static Animation FallingRIGHT = AnimationLoader.megaFallRight();
		public static Animation CrouchingRIGHT = AnimationLoader.megaCrouchRight();
		public static Animation DashingRIGHT = AnimationLoader.megaDashRight();
		public static Animation StandingWhileShootingRIGHT = AnimationLoader.megaStandWhileShootingRight();
		
	// Animation Variables Looking Left
		public static Animation StandingLEFT = AnimationLoader.megaStandLeft();
		public static Animation RunningLEFT = AnimationLoader.megaRunLeft();
		public static Animation JumpingLEFT = AnimationLoader.megaJumpLeft();
		public static Animation FallingLEFT = AnimationLoader.megaFallLeft();
		public static Animation CrouchingLEFT = AnimationLoader.megaCrouchLeft();
		public static Animation DashingLEFT = AnimationLoader.megaDashLeft();
		public static Animation StandingWhileShootingLEFT = AnimationLoader.megaStandWhileShootingLeft();
		
	// Booleans that check the State of the PLayer
		public static boolean Paused = false;
		public static boolean LookingLeft = false;
		public static boolean LandThenStand = true;
		public static boolean CanCrouch = true;
		public static boolean IsCrouching = false;
		public static boolean JumpButtonIsPressed = false;
		public static boolean IsDashJumping = false;
		public static boolean IsShooting = false;
		
		//Collision Related Variables
		public static CollisionRectangle CollisionDetector;
		public static CollisionRectangle CollisionDetectorAbove;
		public static CollisionRectangle CollisionDetectorBelow;
		public static CollisionRectangle CollisionDetectorLeft;
		public static CollisionRectangle CollisionDetectorRight;

		// Helpfull Variables
		public static boolean CanDropDown = true;
		public static boolean CanMoveLeft = true;
		public static boolean CanMoveRight = true;
		public static boolean FallingToFLoor = false;
		public static int TileCollisionCountAbove = 0;
		public static int TileCollisionCountRight = 0;
		public static int TileCollisionCountBelow = 0;
		public static int TileCollisionCountLeft = 0;
		public static int StandingWidth = 60;
		public static int StandingHeight = 68;

	public DMastaGX(){
		
		// Player & Sprite class constructor requires an Animation Object so this provides it.
		super(StandingRIGHT); 
		
		CollisionDetector = new CollisionRectangle();
		CollisionDetectorAbove = new CollisionRectangle();
		CollisionDetectorBelow = new CollisionRectangle();
		CollisionDetectorLeft = new CollisionRectangle();
		CollisionDetectorRight = new CollisionRectangle();
	}
	
	public void UpdateDMastaGX(long elapsedTime){
		
		// Handle Keys Pressed According to the Key Pressed Booleans
		reactToKeysPressed();
		// Handle Keys Released According to the Key Released Booleans
		reactToKeysReleased();
		
		// Call the Parent Class's Update Method
		super.UpdatePlayer(elapsedTime);	
		
		// Update TileCollision Rectangles
		CollisionDetector.UpdateDMastaGXCollisionRectangle(MasterGX);
		CollisionDetectorAbove.UpdateDMastaGXCollisionRectangleAbove(MasterGX);
		CollisionDetectorBelow.UpdateDMastaGXCollisionRectangleBelow(MasterGX);
		CollisionDetectorLeft.UpdateDMastaGXCollisionRectangleLeft(MasterGX);
		CollisionDetectorRight.UpdateDMastaGXCollisionRectangleRight(MasterGX);
	}
	
	/** Methods to Handle Key Pressed Calculations */
	public static void reactToKeysPressed(){
	
			if(MasterControl.Up_Pressed == true)    DMastaGX.MasterGX.handle_Up();
			if(MasterControl.Down_Pressed == true)  DMastaGX.MasterGX.handle_Down();
			if(MasterControl.Left_Pressed == true)  DMastaGX.MasterGX.handle_Left();
			if(MasterControl.Right_Pressed == true) DMastaGX.MasterGX.handle_Right();
			if(MasterControl.S_Pressed == true)     DMastaGX.MasterGX.handle_S();
			if(MasterControl.A_Pressed == true)     DMastaGX.MasterGX.handle_A();
			if(MasterControl.D_Pressed == true)     DMastaGX.MasterGX.handle_D();
				
	}
	
	/** Methods to Handle Key Released Calculations */
	public static void reactToKeysReleased(){
			
			if(MasterControl.Up_Released == true){
				DMastaGX.MasterGX.stop_Up();
				MasterControl.Up_Released = false;
			}
			if(MasterControl.Down_Released == true){
				DMastaGX.MasterGX.stop_Down();
				MasterControl.Down_Released = false;
			}
			if(MasterControl.Left_Released == true){
				DMastaGX.MasterGX.stop_Left();
				MasterControl.Left_Released = false;
			}
			if(MasterControl.Right_Released == true){
				DMastaGX.MasterGX.stop_Right();
				MasterControl.Right_Released = false;
			}
			if(MasterControl.S_Released == true){
				DMastaGX.MasterGX.stop_S();
				MasterControl.S_Released = false;
			}
			if(MasterControl.A_Released == true){
				DMastaGX.MasterGX.stop_A();
				MasterControl.A_Released = false;
			}
			if(MasterControl.D_Released == true){
				DMastaGX.MasterGX.stop_D();
				MasterControl.D_Released = false;
			}
	}
	
	public static void reactToZeroCollisions(){
		
		// Actions to be taken if the Collision Rectangle below doesn't Collide
	  	if(true == DMastaGX.MasterGX.CanDropDown && DMastaGX.MasterGX.TileCollisionCountBelow == 0){
	  		//Only Drop if you're not in In MidAir, and no collisions Below Happened
	  		if(DMastaGX.MasterGX.getState() == 0)DMastaGX.MasterGX.dropToFloor();
	  		DMastaGX.MasterGX.CanDropDown = false;
	  	}	
	  	else DMastaGX.MasterGX.TileCollisionCountBelow = 0;
		
	    // Actions to be taken if the Collision Rectangle Left doesn't Collide
	  	if(DMastaGX.MasterGX.TileCollisionCountLeft == 0)
	  		 DMastaGX.MasterGX.CanMoveLeft = true;	
	  	else DMastaGX.MasterGX.TileCollisionCountLeft = 0;
	  	
		// Actions to be taken if the Collision Rectangle Right doesn't Collide
	  	if(DMastaGX.MasterGX.TileCollisionCountRight == 0)
	  		 DMastaGX.MasterGX.CanMoveRight = true;	
	  	else DMastaGX.MasterGX.TileCollisionCountRight = 0;
	}	  	
	
	// Method that checks which Collision Rectangle is colliding, and adds to the collision count
	public static void reactToCollision(){
		
		// CHECK Collision Rectangle Above
		if(CollisionDetectorAbove.hasCollidedWith(TileMap.TileCollisionDetector)){
			DMastaGX.MasterGX.TileCollisionCountAbove += 1;
			actOnCollisionAbove(TileMap.TileCollisionDetector);
		}
		
		// CHECK Collision Rectangle Below
		if(CollisionDetectorBelow.hasCollidedWith(TileMap.TileCollisionDetector)){
			DMastaGX.MasterGX.TileCollisionCountBelow += 1;
			// Stops Multiple Executions	
		if((int)TileMap.TileCollisionDetector.CoordinateY  - StandingHeight + 3 != DMastaGX.MasterGX.getY())
			actOnCollisionBelow(TileMap.TileCollisionDetector);
		}
		
		// CHECK Collision Rectangle To The Left
		if(CollisionDetectorLeft.hasCollidedWith(TileMap.TileCollisionDetector)){
			DMastaGX.MasterGX.TileCollisionCountLeft += 1;
			// Stops Multiple Executions	
			if(TileMap.TileCollisionDetector.CoordinateX + TileMap.TileCollisionDetector.Width != DMastaGX.MasterGX.getX())	
				actOnCollisionLeft(TileMap.TileCollisionDetector);
		}
		
		// CHECK Collision Rectangle To The Right
		if(CollisionDetectorRight.hasCollidedWith(TileMap.TileCollisionDetector)){
			DMastaGX.MasterGX.TileCollisionCountRight += 1;
			// Stops Multiple Executions	
		if(TileMap.TileCollisionDetector.CoordinateX  - DMastaGX.MasterGX.getWidth() != DMastaGX.MasterGX.getX())	
			actOnCollisionRight(TileMap.TileCollisionDetector);
		}
	}
		
	
	public static void actOnCollisionAbove(CollisionRectangle Obstacle){
		
		//  System.out.println("YOU COLLIDED ABOVE");
		
		DMastaGX.MasterGX.setY(Obstacle.CoordinateY + Obstacle.Height + 1);
		DMastaGX.MasterGX.dropToFloor();
		  
	}

	public static void actOnCollisionBelow(CollisionRectangle Obstacle){
		
		//System.out.println("YOU COLLIDED BELOW");
		
		DMastaGX.MasterGX.setFloorY((int)Obstacle.CoordinateY  - StandingHeight + 3);

		DMastaGX.MasterGX.CanDropDown = true;
		
		DMastaGX.MasterGX.FallingToFLoor = false;
	}

	public static void actOnCollisionLeft(CollisionRectangle Obstacle){
		
		System.out.println("YOU COLLIDED LEFT " + DMastaGX.MasterGX.TileCollisionCountLeft);

		DMastaGX.MasterGX.CanMoveLeft = false;
		
		DMastaGX.MasterGX.setX(Obstacle.CoordinateX + Obstacle.Width);
		
}
	
	public static void actOnCollisionRight(CollisionRectangle Obstacle){
		
		  System.out.println("YOU COLLIDED RIGHT " + DMastaGX.MasterGX.TileCollisionCountRight);
			
		  DMastaGX.MasterGX.CanMoveRight = false;
		  
		  DMastaGX.MasterGX.setX(Obstacle.CoordinateX  - StandingWidth);
		 
		}
	
	/** Methods to Handle Key Pressed Calculations */
	public static void handle_Up(){
	}
	
	public static void handle_Down(){
		
		// Only Crouch when you're NOT moving AND are On The Floor. When he crouches lower his height by adding 14.
		if(DMastaGX.MasterGX.getVelocityX() == 0 && DMastaGX.MasterGX.getState() == 0 && DMastaGX.IsCrouching == false){
		   DMastaGX.MasterGX.setY(DMastaGX.MasterGX.getY() + 14);
		   if(DMastaGX.MasterGX.LookingLeft == false)	
		   DMastaGX.MasterGX.changeAnimation(DMastaGX.CrouchingRIGHT);
		   else  DMastaGX.MasterGX.changeAnimation(DMastaGX.CrouchingLEFT);
		   DMastaGX.IsCrouching = true; 
		} 
	}
	
	public static void handle_Left(){
		
	// If you Can't move left because an Object is in the way Change Animations	
		if(false == DMastaGX.MasterGX.CanMoveLeft){ 
			
		 if(DMastaGX.MasterGX.getState() == 0)  DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.StandingLEFT);
		 else{ // If you're in midair and you press Left look to the Left in Mid Air
			if(false == DMastaGX.MasterGX.FallingToFLoor) DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.JumpingLEFT);
			if(true == DMastaGX.MasterGX.FallingToFLoor) DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.FallingLEFT);
   }
}
		
		else{
		
		// The player will run right after landing   
		DMastaGX.LandThenStand = false; 
	    // Left was pressed ; this will help rotate the image to the left
		DMastaGX.LookingLeft = true;   
		// IF the player is Crouching and you Move he will get up and Run
		if(DMastaGX.IsCrouching == true){
			DMastaGX.MasterGX.setY(DMastaGX.MasterGX.getY() - 14);
			DMastaGX.IsCrouching = false;
		}
		// Only Change to Running Animation if the Player is on the ground
		if(DMastaGX.MasterGX.getState() == 0)
		if(DMastaGX.MasterGX.LookingLeft == false)	
		   DMastaGX.MasterGX.changeAnimation(DMastaGX.RunningRIGHT);
		else DMastaGX.MasterGX.changeAnimation(DMastaGX.RunningLEFT);
		
		// If you're in midair and you press Left look to the Left in Mid Air
		if(DMastaGX.MasterGX.getState() == 1){
			if(false == DMastaGX.MasterGX.FallingToFLoor) DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.JumpingLEFT);
			if(true == DMastaGX.MasterGX.FallingToFLoor) DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.FallingLEFT);
		}
		
		// Set Velocity
//		   DMastaGX.MasterGX.setVelocityX(-0.3f);
		}
	}
	
public static void handle_Right(){
	
	// If you Can't move left because an Object is in the way Change Animations	
	if(false == DMastaGX.MasterGX.CanMoveRight){ 
		
	 if(DMastaGX.MasterGX.getState() == 0)  DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.StandingRIGHT);
	 else{ // If you're in midair and you press Left look to the Left in Mid Air
		if(false == DMastaGX.MasterGX.FallingToFLoor) DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.JumpingRIGHT);
		if(true == DMastaGX.MasterGX.FallingToFLoor) DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.FallingRIGHT);
   }
}
	
		else{
		
		// The player will run right after landing 
		DMastaGX.MasterGX.LandThenStand = false;
		// Right was pressed ; this will help rotate the image to the right
		DMastaGX.MasterGX.LookingLeft = false;   
		// IF the player is Crouching and you Move he will get up and Run
		if(DMastaGX.MasterGX.IsCrouching == true){
			DMastaGX.MasterGX.setY(DMastaGX.MasterGX.getY() - 14);
			DMastaGX.MasterGX.IsCrouching = false;
		}
		// Only Change to Running Animation if the Player is on the ground
		if(DMastaGX.MasterGX.getState() == 0)
			if(DMastaGX.MasterGX.LookingLeft == false)	
		   DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.RunningRIGHT);
			else DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.RunningLEFT);
		
		// If you're in midair and you press Right look to the right in Mid Air
		if(DMastaGX.MasterGX.getState() == 1){
		  if(false == DMastaGX.MasterGX.FallingToFLoor) DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.JumpingRIGHT);
		  if(true == DMastaGX.MasterGX.FallingToFLoor) DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.FallingRIGHT);
		}	
			
		// Set Velocity
//		DMastaGX.MasterGX.setVelocityX(0.3f);
		}
	}
	
	public static void handle_S(){
		

		// Disables Rapidfire by Making sure you can only Jump once you release the button 
		if (DMastaGX.JumpButtonIsPressed == false) {
			// Marks Jump Button as Pressed
			DMastaGX.JumpButtonIsPressed = true;
		//If The Player is Crouching He will stand up
		if(DMastaGX.IsCrouching == true){
			DMastaGX.MasterGX.setY(DMastaGX.MasterGX.getY() - 14);
			DMastaGX.IsCrouching = false;
		}
		//Change to Jumping Animation and Jump if The PLayer is On the Floor
		if(DMastaGX.MasterGX.getState() == 0){ 
			
			   // Jumping Method 
			  DMastaGX.MasterGX.jump();
			  
			if(DMastaGX.MasterGX.LookingLeft == false)		
		   DMastaGX.MasterGX.changeAnimation(DMastaGX.JumpingRIGHT);
			else DMastaGX.MasterGX.changeAnimation(DMastaGX.JumpingLEFT);
		   //Set the Floor Below the map
		//   DMastaGX.MasterGX.setFloorY(1500);
		}
		}
	}
	
	public static void handle_A(){
		
		// IF the player is Crouching and you Dash he will get up
		if(DMastaGX.IsCrouching == true){
			DMastaGX.MasterGX.setY(DMastaGX.MasterGX.getY() - 14);
			DMastaGX.IsCrouching = false;
		}
		// Only Dash if the Player is in the ground
		 if(DMastaGX.MasterGX.getState() == 0){
			 if(DMastaGX.MasterGX.LookingLeft == false)
		   DMastaGX.MasterGX.changeAnimation(DMastaGX.DashingRIGHT);
			 else DMastaGX.MasterGX.changeAnimation(DMastaGX.DashingLEFT);
			 
		// Dash to the Right if the player is looking Right	
//		   if(TheGoods.LookingLeft == false)DMastaGX.MasterGX.setVelocityX(0.6f);
		// Dash to the Left if the Player is Looking Left
//		   if(TheGoods.LookingLeft == true)DMastaGX.MasterGX.setVelocityX(-0.6f); 
		   }
		 
	}
	
	public static void handle_D(){
		
		DMastaGX.IsShooting = true;
		
		// IF the player is Crouching and you Shoot he will get up and Run
		if(DMastaGX.IsCrouching == true){
			DMastaGX.MasterGX.setY(DMastaGX.MasterGX.getY() - 14);
			DMastaGX.IsCrouching = false;
		}
		
		 if(DMastaGX.MasterGX.LookingLeft == false)
		DMastaGX.MasterGX.changeAnimation(DMastaGX.StandingWhileShootingRIGHT);
		 else DMastaGX.MasterGX.changeAnimation(DMastaGX.StandingWhileShootingLEFT);
	}
	
	/** Methods to Handle Key Released Calculations */
	public static void stop_Up(){
	}
	
	public static void stop_Down(){

		// Stand Up when you let go of the Crouch Button and the Player is NOT moving
		if(DMastaGX.MasterGX.getVelocityX() == 0 && DMastaGX.IsCrouching == true){
			if(DMastaGX.MasterGX.LookingLeft == false)	
		   DMastaGX.MasterGX.changeAnimation(DMastaGX.StandingRIGHT);
			else DMastaGX.MasterGX.changeAnimation(DMastaGX.StandingLEFT);
		   DMastaGX.MasterGX.setY(DMastaGX.MasterGX.getY() - 14);
		   DMastaGX.IsCrouching = false;
		}
		// Don't Crouch in midair
		if(DMastaGX.CanCrouch == false)
			if(DMastaGX.MasterGX.LookingLeft == false)
			DMastaGX.MasterGX.changeAnimation(DMastaGX.FallingRIGHT);
			else DMastaGX.MasterGX.changeAnimation(DMastaGX.FallingLEFT);
	}
	
	public static void stop_Left(){
		
		// Change Player to the Standing Animation when he's on the floor and not moving to the right
		if(DMastaGX.MasterGX.getState() == 0 && DMastaGX.MasterGX.getVelocityX() != 0.3f)
			if(DMastaGX.MasterGX.LookingLeft == false)
			DMastaGX.MasterGX.changeAnimation(DMastaGX.StandingRIGHT);
			else DMastaGX.MasterGX.changeAnimation(DMastaGX.StandingLEFT);
		// Stop the Player when he releases the Left Key and the Right Key is not being held
		if(DMastaGX.MasterGX.getVelocityX() != 0.3f)DMastaGX.MasterGX.setVelocityX(0);
		// This helps determine if the user will Stand or Run after Landing
		if(DMastaGX.MasterGX.getVelocityX() != 0.3f )DMastaGX.LandThenStand = true;
		
	}
	
	public static void stop_Right(){
		
		if(DMastaGX.MasterGX.getState() == 0 && DMastaGX.MasterGX.getVelocityX() != -0.3f)
			if(DMastaGX.MasterGX.LookingLeft == false)
			DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.StandingRIGHT);
			else  DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.StandingLEFT);
		// Stop the Player when he releases the Right Key and the Left Key is not being held
		if(DMastaGX.MasterGX.getVelocityX() != -0.3f)DMastaGX.MasterGX.setVelocityX(0);
		// This helps determine if the user will Stand or Run after Landing
		if(DMastaGX.MasterGX.getVelocityX() != -0.3f)DMastaGX.LandThenStand = true;
		
	}
	
	public static void stop_S(){
		
		// Change to Faling Animation If the PLayer is in MidAir AND the Jumping button is released
		if(DMastaGX.MasterGX.getState() == 1 && DMastaGX.FallingToFLoor == false) DMastaGX.MasterGX.dropToFloor();
		
		DMastaGX.JumpButtonIsPressed = false;
		
	}
	
	public static void stop_A(){
		
		// If the player is in Mid Air when Dash was released he is Dash Jumping
		if(DMastaGX.MasterGX.getState() == 1)DMastaGX.IsDashJumping = true;
		//End the Dash Animation when The Dash Button is released and He's in the floor
		if(DMastaGX.MasterGX.getState() == 0){
		DMastaGX.MasterGX.setVelocityX(0);
		if(DMastaGX.MasterGX.LookingLeft == false)
		DMastaGX.MasterGX.changeAnimation(DMastaGX.StandingRIGHT);
		else DMastaGX.MasterGX.changeAnimation(DMastaGX.StandingLEFT);
		}
	}
	
	public static void stop_D(){
		
		DMastaGX.IsShooting = false;
		
		if(DMastaGX.MasterGX.LookingLeft == false)
		DMastaGX.MasterGX.changeAnimation(DMastaGX.MasterGX.StandingRIGHT);
		else DMastaGX.MasterGX.changeAnimation(DMastaGX.StandingLEFT);
	}
	
	   public static void draw(Graphics g, DMastaGX MasterGX){
		   
		//  Draw The Player  
		 g.drawImage(MasterGX.getImage(),
		 (int)MasterGX.getX() , (int)MasterGX.getY(),
		 MasterGX.getWidth(),MasterGX.getHeight(), null);
      	 
	   //  Draw The Collision Detecting Rectangles
		     //CollisionDetector.draw(g, "");
	         CollisionDetectorAbove.draw(g, "");
	         CollisionDetectorBelow.draw(g, "");
	         CollisionDetectorLeft.draw(g, ""); 
	         CollisionDetectorRight.draw(g, "");
		   
  } 

	public void run(){
		
		MasterGX = new DMastaGX();
		MasterGX.setX(400); // Default = 400
		MasterGX.setY(-500); // Default = 435
		MasterGX.setFloorY(1500); // Default = 432
	}
		
}